package com.nami.store.biz.conver.repository.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.nami.store.biz.conver.repository.ConverRepository;
import com.nami.store.domain.ConversationDO;
import com.nami.store.mapper.ConversationMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.BatchResult;
import org.dromara.common.core.utils.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;


/**
 * <p>
 * 会话 服务实现类
 * </p>
 *
 * @author lbc
 * @since 2023-08-01
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ConversationServiceImpl implements ConverRepository {

    private final ConversationMapper baseMapper;

    @Override
    public boolean updateMySelfConver(ConversationDO conver) {
        boolean exist = isExist(conver.getUserId(), conver.getTargetId());
        if (!exist) {
            this.saveConver(conver);
            return Boolean.TRUE;
        }

        LambdaUpdateWrapper<ConversationDO> wrapper = new LambdaUpdateWrapper<ConversationDO>();
        wrapper.eq(ConversationDO::getUserId, conver.getUserId());
        wrapper.eq(ConversationDO::getTargetId, conver.getTargetId());

        wrapper.set(ConversationDO::getLatestMsg, conver.getLatestMsg());
        wrapper.set(ConversationDO::getLatestMsgId, conver.getLatestMsgId());
        wrapper.set(ConversationDO::getSyncTime, conver.getSyncTime());
        wrapper.set(ConversationDO::getSortTime, conver.getSortTime());

        baseMapper.update(wrapper);
        return Boolean.TRUE;
    }

    @Override
    public boolean updateReceiverConver(ConversationDO conver) {
        boolean exist = isExist(conver.getUserId(), conver.getTargetId());
        if (!exist) {
            this.saveConver(conver);
            return Boolean.TRUE;
        }

        LambdaUpdateWrapper<ConversationDO> wrapper = new LambdaUpdateWrapper<ConversationDO>();

        wrapper.eq(ConversationDO::getUserId, conver.getUserId());
        wrapper.eq(ConversationDO::getTargetId, conver.getTargetId());

        wrapper.set(ConversationDO::getLatestMsg, conver.getLatestMsg());
        wrapper.set(ConversationDO::getLatestMsgId, conver.getLatestMsgId());
        wrapper.set(ConversationDO::getLatestUnreadMsgIndex, conver.getLatestUnreadMsgIndex());
        wrapper.set(ConversationDO::getSyncTime, conver.getSyncTime());
        wrapper.set(ConversationDO::getSortTime, conver.getSortTime());

        baseMapper.update(wrapper);
        return Boolean.TRUE;
    }

    @Override
    public boolean saveConver(ConversationDO conver) {
        if (conver == null) {
            return Boolean.FALSE;
        }
        baseMapper.insert(conver);
        return Boolean.TRUE;
    }

    @Override
    public boolean isExist(String userId, String targetId) {
        return baseMapper.exists(new LambdaQueryWrapper<ConversationDO>()
            .eq(ConversationDO::getUserId, userId)
            .eq(ConversationDO::getTargetId, targetId));
    }


    @Override
    public boolean updateGrpConvers(ConversationDO conversation) {
        // 更新我自己的read index, read msg time, 我发消息，肯定我之前消息是已读
        baseMapper.update(new LambdaUpdateWrapper<ConversationDO>()
            .eq(ConversationDO::getUserId, conversation.getUserId())
            .eq(ConversationDO::getTargetId, conversation.getTargetId())
            .eq(ConversationDO::getAppKey, conversation.getAppKey())

            .set(ConversationDO::getLatestReadMsgIndex, conversation.getLatestReadMsgId())
            .set(ConversationDO::getLatestReadMsgTime, conversation.getLatestReadMsgTime())
        );
        // 我发消息，更新所有成员的消息最大seq, 最新消息id, 最新sort time,包括我自己
        baseMapper.update(new LambdaUpdateWrapper<ConversationDO>()
            .eq(ConversationDO::getTargetId, conversation.getTargetId())
            .eq(ConversationDO::getAppKey, conversation.getAppKey())
            .set(ConversationDO::getLatestMsgId, conversation.getLatestMsgId())
            .set(ConversationDO::getLatestUnreadMsgIndex, conversation.getLatestUnreadMsgIndex())
            .set(ConversationDO::getSortTime, conversation.getSortTime())
            .set(ConversationDO::getSyncTime, conversation.getSyncTime())
        );
        return Boolean.TRUE;
    }

    @Override
    public boolean updateConver(ConversationDO conversation) {

        baseMapper.update(new LambdaUpdateWrapper<ConversationDO>()
            .eq(ConversationDO::getAppKey, conversation.getAppKey())
            .eq(ConversationDO::getUserId, conversation.getUserId())
            .eq(ConversationDO::getTargetId, conversation.getTargetId())

            .set(ConversationDO::getLatestMsgId, conversation.getLatestMsgId())
            .set(ConversationDO::getLatestUnreadMsgIndex, conversation.getLatestUnreadMsgIndex())

            .set(ConversationDO::getLatestReadMsgTime, conversation.getLatestReadMsgTime())
            .set(ConversationDO::getLatestReadMsgId, conversation.getLatestReadMsgId())
            .set(ConversationDO::getLatestMsg, conversation.getLatestMsg())
            .set(ConversationDO::getLatestReadMsgIndex, conversation.getLatestReadMsgIndex())

            .set(ConversationDO::getIfMute, conversation.getIfMute())
            .set(ConversationDO::getIfTop, conversation.getIfTop())

            .set(ConversationDO::getSortTime, conversation.getSortTime())
            .set(ConversationDO::getSyncTime, conversation.getSyncTime())
        );

        return Boolean.TRUE;
    }

    @Override
    public ConversationDO getConversation(String appKey, String userId, String targetId) {
        if (StringUtils.isBlank(appKey) || StringUtils.isBlank(userId) || StringUtils.isBlank(targetId)) {
            return null;
        }
        ConversationDO exist = baseMapper.selectOne(new LambdaQueryWrapper<ConversationDO>()
            .eq(ConversationDO::getAppKey, appKey)
            .eq(ConversationDO::getUserId, userId)
            .eq(ConversationDO::getTargetId, targetId)
        );
        if (exist == null) {
            return null;
        }
        return exist;
    }

    @Override
    public List<ConversationDO> getConversByUserIds(String appKey, List<String> userIds, String targetId) {
        if (StringUtils.isBlank(appKey) || CollUtil.isEmpty(userIds) || StringUtils.isBlank(targetId)) {
            return null;
        }
        List<ConversationDO> conversations = baseMapper.selectList(new LambdaQueryWrapper<ConversationDO>()
            .eq(ConversationDO::getAppKey, appKey)
            .in(ConversationDO::getUserId, userIds)
            .eq(ConversationDO::getTargetId, targetId)
        );
        return conversations;
    }

    @Override
    public boolean batchSave(List<ConversationDO> convers) {
        List<BatchResult> insert = baseMapper.insert(convers);
        return Boolean.TRUE;

    }

    @Override
    public boolean batchUpdConvers(List<ConversationDO> itemList) {
        TimeInterval timer = DateUtil.timer();
        if (CollUtil.isEmpty(itemList)) {
            return Boolean.FALSE;
        }

        // 这三行等同于底下的updateById(list);
//        MybatisBatch<Conversation> mybatisBatch = new MybatisBatch<>(sqlSessionFactory, itemList);
//        MybatisBatch.Method<Conversation> method = new MybatisBatch.Method<>(ConversationMapper.class);
//        mybatisBatch.execute(method.updateById());
        List<BatchResult> batchResults = baseMapper.updateById(itemList);

//        int totalUpdated = 0;
//        int batchSize = 500; // 每批更新的记录数
//        int listSize = itemList.size();
//
//        for (int i = 0; i < listSize; i += batchSize) {
//            // 计算每批的末尾索引，确保不会超出列表范围
//            int end = Math.min(i + batchSize, listSize);
//            // 获取当前批次的数据子列表
//            List<Conversation> subList = itemList.subList(i, end);
//            // 执行批量更新
//            int updated = baseMapper.updateGrpConvers(subList);
//            // 累加更新成功的记录数
//            totalUpdated += updated;
//        }

//        int result = baseMapper.updateGrpConvers(itemList);


//        int totalUpdated = 0;
//        int batchSize = 1000; // 每批更新的记录数
//        int listSize = itemList.size();
//
//        for (int i = 0; i < listSize; i += batchSize) {
//            // 计算每批的末尾索引，确保不会超出列表范围
//            int end = Math.min(i + batchSize, listSize);
//            // 获取当前批次的数据子列表
//            List<Conversation> subList = itemList.subList(i, end);
//            // 执行批量更新
//            int updated = baseMapper.batchUpdGrpConvers(subList);
//            // 累加更新成功的记录数
//            totalUpdated += updated;
//        }

//        List<LambdaUpdateWrapper<Conversation>> updateWrappers = itemList.stream()
//            .map(conversation -> new LambdaUpdateWrapper<Conversation>()
//                .eq(Conversation::getAppKey, conversation.getAppKey())
//                .eq(Conversation::getUserId, conversation.getUserId())
//                .eq(Conversation::getTargetId, conversation.getTargetId())
//                .set(Conversation::getLatestMsgId, conversation.getLatestMsgId())
//                .set(Conversation::getLatestUnreadMsgIndex, conversation.getLatestUnreadMsgIndex())
//
//                .set(Conversation::getLatestReadMsgTime, conversation.getLatestReadMsgTime())
//                .set(Conversation::getLatestReadMsgId, conversation.getLatestReadMsgId())
//                .set(Conversation::getLatestMsg, conversation.getLatestMsg())
//                .set(Conversation::getLatestReadMsgIndex, conversation.getLatestReadMsgIndex())
//
//                .set(Conversation::getIfMute, conversation.getIfMute())
//                .set(Conversation::getIfTop, conversation.getIfTop())
//
//                .set(Conversation::getSortTime, conversation.getSortTime())
//                .set(Conversation::getSyncTime, conversation.getSyncTime())
//            ).collect(Collectors.toList());
//
//

        log.warn("[convers] grp conver upd action. result={}, use={}ms", itemList.size(), timer.interval());
        return Boolean.TRUE;
    }

    @Override
    public boolean insertOrUpd(ConversationDO conver) {
        return baseMapper.insertOrUpd(conver);
    }

    @Override
    public List<ConversationDO> getConversByUserIds(String appKey, String userId, List<String> targetIds) {
        return baseMapper.selectList(new LambdaQueryWrapper<ConversationDO>()
            .eq(ConversationDO::getAppKey, appKey)
            .eq(ConversationDO::getUserId, userId)
            .in(ConversationDO::getTargetId, targetIds)
        );
    }

}
